package aiku.numericalcontroloa.Service.Impl;

import aiku.numericalcontroloa.Base.Utils.BaseEnum;
import aiku.numericalcontroloa.Base.Utils.HttpStatus;
import aiku.numericalcontroloa.Base.Utils.Result;
import aiku.numericalcontroloa.Mapper.*;
import aiku.numericalcontroloa.Mapper.MasterControl.MessageNotificationMapper;
import aiku.numericalcontroloa.Model.Dto.ExpenseDto;
import aiku.numericalcontroloa.Model.Dto.PurchasePartDto;
import aiku.numericalcontroloa.Model.Entity.*;
import aiku.numericalcontroloa.Model.Entity.MasterControl.MessageNotification;
import aiku.numericalcontroloa.Model.Vo.ExpenseVo;
import aiku.numericalcontroloa.common.utils.DateUtils;
import aiku.numericalcontroloa.enums.RoleEnum;
import aiku.numericalcontroloa.project.system.pojo.entity.SysRole;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import aiku.numericalcontroloa.Service.ExpenseService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 马
 * @description 针对表【expense】的数据库操作Service实现
 * @createDate 2024-03-25 16:39:09
 */
@Service
public class ExpenseServiceImpl extends ServiceImpl<ExpenseMapper, Expense>
        implements ExpenseService {
    @Autowired
    private ExpenseMapper expenseMapper;
    @Autowired
    private PurchasePartMapper purchasePartMapper;
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RemarksMapper remarksMapper;
    @Autowired
    private PaymentBillingMapper paymentBillingMapper;
    @Autowired
    private MessageNotificationMapper msgNotificationMapper;
    @Autowired
    private DevicesMapper devicesMapper;

    /**
     * 用户申请审核
     * 
     * @param
     * @return
     */
    @Override
    @Transactional
    public Result addExpense(ExpenseDto expenseDto) {
        if (expenseDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        Expense expense = new Expense();
        // 申请人
        expense.setUserId(StpUtil.getLoginIdAsString());
        // 报销金额
        if (expenseDto.getPrice() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数");
        }
        expense.setPrice(expenseDto.getPrice());
        // 报销说明
        if (expenseDto.getInfo() != null) {
            expense.setInfo(expenseDto.getInfo());
        }
        // 附加图
        if (expenseDto.getImage() != null) {
            expense.setImage(expenseDto.getImage());
        }
        // 状态，待管理员审核
        expense.setStatus(0);
        // 插入数据
        expenseMapper.insert(expense);

        if (expenseDto.getRemarks() != null) {
            Remarks remarks = new Remarks();
            remarks.setQueryId(expense.getId());
            remarks.setRemarkContent(expenseDto.getRemarks());
            remarksMapper.insert(remarks);
        }

        // 创建消息通知
        // 查管理员角色
        LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
        userLQW.eq(User::getState, BaseEnum.USER_INCUMBENCY.getCodeInt())
                .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
        List<User> userList = userMapper.selectList(userLQW);
        if (!userList.isEmpty()) {
            List<MessageNotification> msgList = new ArrayList<>();
            for (User admin : userList) {
                MessageNotification msg = new MessageNotification();
                msg.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                // 标题
                msg.setTitle("有新的报销申请待审批");
                // 内容
                String content = admin.getNickName() + "申请报销" + expense.getPrice() + "元";
                msg.setContent(content);
                // 发布人为申请人
                msg.setPublisherId(expense.getUserId());
                // 接收人为管理员
                msg.setReceiverId(admin.getId());
                // 关联id
                msg.setRelevanceId(expense.getId());
                // 类型为报销管理
                msg.setMsgType(8);
                // 子菜单为1报销列表
                msg.setSubmenu(1);
                // 状态为待处理
                msg.setStatus(0);
                msg.setCreateTime(new Date());
                msgList.add(msg);
            }
            msgNotificationMapper.insertBatch(msgList);
        }
        return Result.success("添加成功");
    }

    /**
     * 管理审核通过
     * 
     * @param id
     * @return
     */
    @Override
    public Result examineUpdate(String id, Integer status) {
        String userid = StpUtil.getLoginId().toString();
        // 先查询是否有该订单
        Expense expense = expenseMapper.selectById(id);
        if (expense == null) {
            return Result.error(201, "该订单不存在");
        }
        // 查询权限是否管理员
        SysRole adminInfo = userService.isAdminInfo(userid);
        if (adminInfo.getId() == RoleEnum.ROLE_6.getCode()) {
            Expense expense2 = new Expense();
            expense2.setId(id);
            expense2.setStatus(0);
            int i = expenseMapper.updateById(expense2);
            return i > 0 ? Result.success("修改成功") : Result.error(201, "修改失败");
        }
        if (adminInfo.getId() != RoleEnum.ROLE_1.getCode()) {
            return Result.error(201, "权限不足");
        }
        Expense expense2 = new Expense();
        expense2.setId(id);
        expense2.setStatus(status);
        int i = expenseMapper.updateById(expense2);
        return i > 0 ? Result.success("修改成功") : Result.error(201, "修改失败");
    }

    /**
     * 管理员查询报销记录
     * 
     * @return
     */
    @Override
    public Result examineList() {
        String userid = StpUtil.getLoginId().toString();
        SysRole adminInfo = userService.isAdminInfo(userid);
        LambdaQueryWrapper<Expense> queryWrapper = new LambdaQueryWrapper<>();
        // 按时间排序,时间越新越靠前
        if (adminInfo.getId() == RoleEnum.ROLE_1.getCode()) {
            // 管理
        } else if (adminInfo.getId() == RoleEnum.ROLE_6.getCode()) {
            // 财务,如果是财务则只查询当前财务的订单
        } else {
            queryWrapper.eq(Expense::getUserId, userid);
        }

        List<Expense> expenses = expenseMapper.selectList(queryWrapper);
        if (expenses.isEmpty()) {
            return Result.success(expenses);
        }
        for (Expense e : expenses) {
            User user = userMapper.selectByIdWithDelete(e.getUserId());
        }

        // List<String> list =
        // expenses.stream().map(Expense::getUserId).collect(Collectors.toList());
        // List<User> userList = userMapper.selectList(new
        // LambdaQueryWrapper<User>().in(BaseEntity::getId, list));
        // expenses.forEach(expense -> {
        // userList.forEach(user -> {
        // if (expense.getUserId().equals(user.getId())) {
        // expense.setUserName(user.getNickName());
        // }
        // });
        // });
        return Result.success(expenses);
    }

    @Override
    public Result getExpenseList(ExpenseDto expenseDto) {
        if (expenseDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "参数为空(expenseDto is null)");
        }
        if (expenseDto.getCurrentPage() == null || expenseDto.getPageSize() == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少分页参数");
        }
        Page<Expense> expensePage = new Page<>(expenseDto.getCurrentPage(), expenseDto.getPageSize());
        // 条件查询
        LambdaQueryWrapper<Expense> expenseLQW = new LambdaQueryWrapper<>();
        expenseLQW.orderByDesc(Expense::getCreateTime);

        User loginUser = userMapper.selectById(StpUtil.getLoginIdAsString());
        boolean role = loginUser.getRoleId().equals(RoleEnum.ROLE_1.getCodeToString()) ||
                loginUser.getRoleId().equals(RoleEnum.ROLE_5.getCodeToString()) ||
                loginUser.getRoleId().equals(RoleEnum.ROLE_6.getCodeToString());

        // 根据申请人查询
        if (role && expenseDto.getUserId() != null) {
            expenseLQW.eq(Expense::getUserId, expenseDto.getUserId());
        } else if (!role) {
            expenseLQW.eq(Expense::getUserId, loginUser.getId());
        }
        // 根据状态查询
        if (expenseDto.getStatus() != null) {
            expenseLQW.eq(Expense::getStatus, expenseDto.getStatus());
        }

        if (expenseDto.getDateStart() != null && expenseDto.getDateEnd() != null) {
            expenseLQW.ge(Expense::getCreateTime,
                    LocalDate.parse(expenseDto.getDateStart(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

        if (expenseDto.getDateStart() != null && expenseDto.getDateEnd() != null) {
            expenseLQW.lt(Expense::getCreateTime,
                    LocalDate.parse(expenseDto.getDateEnd(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).plusMonths(1));
        }

        // List<Expense> expenseList = expenseMapper.selectPage(expensePage,
        // expenseLQW).getRecords();
        List<Expense> expenseList = expenseMapper.selectList(expenseLQW);

        Map<String, Object> map = new HashMap<>();
        List<ExpenseVo> expenseVoList = new ArrayList<>();
        if (expenseList.isEmpty()) {
            map.put("total", expensePage.getTotal());
            map.put("expenseVoList", expenseVoList);
            return Result.success("查询成功", map);
        }

        // 查采购订单零件列表
        List<String> purchaseIdList = expenseList.stream().map(Expense::getPurchaseId).filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (purchaseIdList.isEmpty()) {
            purchaseIdList.add("");
        }
        LambdaQueryWrapper<PurchasePart> partLQW = new LambdaQueryWrapper<>();
        partLQW.in(PurchasePart::getPurchaseId, purchaseIdList);
        List<PurchasePart> purchasePartList = purchasePartMapper.selectList(partLQW);
        // 查产品列表
        Set<String> partIdList = purchasePartList.stream().map(PurchasePart::getPartId).collect(Collectors.toSet());
        if (partIdList.isEmpty()) {
            partIdList.add("");
        }
        List<Devices> devicesList = devicesMapper.selectBatchByIdWithDelete(partIdList);
        // 根据deviceId获取device对象
        Map<String, Devices> devicesMap = devicesList.stream()
                .collect(Collectors.toMap(Devices::getId, Function.identity()));
        // 根据采购id获取零件列表
        Map<String, List<PurchasePartDto>> purchasePartMap = new HashMap<>();
        for (PurchasePart purchasePart : purchasePartList) {
            Devices devices = devicesMap.get(purchasePart.getPartId());
            PurchasePartDto purchasePartDto = new PurchasePartDto();
            BeanUtils.copyProperties(purchasePart, purchasePartDto);
            // 零件名
            purchasePartDto.setPartName(devices.getPartName());
            // 零件型号
            purchasePartDto.setModel(devices.getModel());
            // 零件图片
            purchasePartDto.setImage(devices.getImage());
            // 描述
            purchasePartDto.setDevicesDescribe(devices.getDevicesDescribe());
            // 备注
            purchasePartDto.setRemark(devices.getRemark());
            if (!purchasePartMap.containsKey(purchasePart.getPurchaseId())) {
                // 没有采购订单id的key,新建零件集合
                List<PurchasePartDto> partDtoList = new ArrayList<>();
                partDtoList.add(purchasePartDto);
                purchasePartMap.put(purchasePart.getPurchaseId(), partDtoList);
            } else {
                purchasePartMap.get(purchasePart.getPurchaseId()).add(purchasePartDto);
            }
        }

        // 根据申请人id查用户
        List<String> expenseIdList = expenseList.stream().map(Expense::getId).collect(Collectors.toList());
        Set<String> userIdList = expenseList.stream().map(Expense::getUserId).collect(Collectors.toSet());
        List<User> userList = userMapper.selectBatchByIdWithDelete(userIdList);
        // 根据userId获取user
        Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

        // 查支出账单
        LambdaQueryWrapper<PaymentBilling> paymentBillingLQW = new LambdaQueryWrapper<>();
        paymentBillingLQW.in(PaymentBilling::getOrderId, expenseIdList);
        List<PaymentBilling> paymentBillingList = paymentBillingMapper.selectList(paymentBillingLQW);
        // 处理成map，key为报销id，value为账单对象
        Map<String, PaymentBilling> paymentBillingMap = paymentBillingList.stream()
                .collect(Collectors.toMap(PaymentBilling::getOrderId, p -> paymentBillingList.stream()
                        .filter(paymentBilling -> paymentBilling.getOrderId().equals(p.getOrderId()))
                        .findFirst()
                        .orElse(null)));

        // 查备注
        LambdaQueryWrapper<Remarks> remarksLQW = new LambdaQueryWrapper<>();
        remarksLQW.in(Remarks::getQueryId, expenseIdList);
        List<Remarks> remarksList = remarksMapper.selectList(remarksLQW);
        Map<String, Remarks> remarksMap = remarksList.stream()
                .collect(Collectors.toMap(Remarks::getQueryId, r -> remarksList.stream()
                        .filter(remarks -> remarks.getQueryId().equals(r.getQueryId()))
                        .findFirst().orElse(null)));

        for (Expense expense : expenseList) {
            ExpenseVo expenseVo = new ExpenseVo();
            BeanUtils.copyProperties(expense, expenseVo);
            // 申请人姓名
            User user = userMap.get(expense.getUserId());
            expenseVo.setUserName(user.getNickName());
            // 分割附加图url
            if (expense.getImage() != null && !expense.getImage().isEmpty()) {
                expenseVo.setImageUrl(expense.getImage().split(";"));
            }
            // 备注
            if (remarksMap.containsKey(expense.getId())) {
                expenseVo.setRemarks(remarksMap.get(expense.getId()).getRemarkContent());
            }
            // 账单状态
            if (expense.getStatus() == 1) {
                // 报销单审核通过，查账单
                if (paymentBillingMap.containsKey(expense.getId())) {
                    PaymentBilling paymentBilling = paymentBillingMap.get(expense.getId());
                    expenseVo.setBillsStatus(paymentBilling.getBillsStatus());
                }
            }
            if (expense.getPurchaseId() != null && !expense.getPurchaseId().isEmpty()) {
                expenseVo.setPartList(purchasePartMap.get(expense.getPurchaseId()));
            }
            expenseVo.setCreateTime(DateUtils.YMDHMSFormat(expense.getCreateTime()));
            expenseVoList.add(expenseVo);
        }

        // 后期新增
        List<ExpenseVo> newList = expenseVoList.stream()
                .filter(value -> !(value.getStatus().equals(1) && (expenseDto.getBillsStatus() != null)
                        && !(value.getBillsStatus().equals(expenseDto.getBillsStatus()))))
                .collect(Collectors.toList());
        int listLength = newList.size();
        int selectPageStart = (int) ((expensePage.getCurrent() - 1) * expensePage.getSize());
        int selectPageEnd = (int) (expensePage.getCurrent() * expensePage.getSize());
        if (selectPageEnd > listLength) {
            selectPageEnd = listLength;
        }
        newList = newList.subList(selectPageStart, selectPageEnd);

        // map.put("total", expensePage.getTotal());
        map.put("total", listLength);
        map.put("expenseVoList", newList);
        return Result.success("查询成功", map);
    }

    @Override
    public Result getExpense(ExpenseDto expenseDto) {
        if (expenseDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "参数为空[expenseDto is null]");
        }
        if (expenseDto.getId() == null || expenseDto.getId().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "参数为空[ expenseDto[id] is null");
        }
        // 查询是否有该报销单
        Expense expense = expenseMapper.selectById(expenseDto.getId());
        if (expense == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该报销单不存在");
        }
        ExpenseVo expenseVo = new ExpenseVo();
        BeanUtils.copyProperties(expense, expenseVo);

        // 申请时间
        expenseVo.setCreateTime(DateUtils.YMDHMSFormat(expense.getCreateTime()));
        // 申请人
        User user = userMapper.selectById(expense.getUserId());
        expenseVo.setUserName(user.getNickName());
        // 备注
        LambdaQueryWrapper<Remarks> remarksLQW = new LambdaQueryWrapper<>();
        remarksLQW.eq(Remarks::getQueryId, expense.getId());
        Remarks remarks = remarksMapper.selectOne(remarksLQW);
        if (remarks != null) {
            expenseVo.setRemarks(remarks.getRemarkContent());
        }
        // 账单状态
        if (expense.getStatus() == 1) {
            LambdaQueryWrapper<PaymentBilling> paymentBillingLQW = new LambdaQueryWrapper<>();
            paymentBillingLQW.eq(PaymentBilling::getOrderId, expense.getId());
            PaymentBilling paymentBilling = paymentBillingMapper.selectOne(paymentBillingLQW);
            expenseVo.setBillsStatus(paymentBilling.getBillsStatus());
        }
        // 图片
        if (expense.getImage() != null && !expense.getImage().isEmpty()) {
            expenseVo.setImageUrl(expense.getImage().split(";"));
        }

        return Result.success("查询成功", expenseVo);
    }

    @Override
    @Transactional
    public Result updateExpense(ExpenseDto expenseDto) {
        if (expenseDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数[expenseDto为空]");
        }
        if (expenseDto.getId() == null || expenseDto.getId().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数[expenseDto.id为空]");
        }
        // 查询是否有该报销单
        Expense expense = expenseMapper.selectById(expenseDto.getId());
        if (expense == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该报销单不存在");
        }
        // 金额
        if (expenseDto.getPrice() != null) {
            expense.setPrice(expenseDto.getPrice());
        }
        // 报销说明
        if (expenseDto.getInfo() != null) {
            expense.setInfo(expenseDto.getInfo());
        }
        // 图片
        if (expenseDto.getImage() != null) {
            expense.setImage(expenseDto.getImage());
        }
        // 状态改为待审核
        expense.setStatus(0);
        // 更新数据
        expenseMapper.updateById(expense);

        // 备注
        if (expenseDto.getRemarks() != null) {
            // 查备注
            LambdaQueryWrapper<Remarks> remarksLQW = new LambdaQueryWrapper<>();
            remarksLQW.eq(Remarks::getQueryId, expense.getId());
            Remarks remarks = remarksMapper.selectOne(remarksLQW);
            if (remarks == null) {
                remarks = new Remarks();
                remarks.setQueryId(expense.getId());
                remarks.setRemarkContent(expenseDto.getRemarks());
                remarksMapper.insert(remarks);
            } else {
                remarks.setRemarkContent(expenseDto.getRemarks());
                remarksMapper.updateById(remarks);
            }
        }
        return Result.success("修改成功");
    }

    @Override
    @Transactional
    public Result examineExpense(ExpenseDto expenseDto) {
        // 只有管理员有权
        User user = userMapper.selectById(StpUtil.getLoginIdAsString());
        if (!user.getRoleId().equals(RoleEnum.ROLE_1.getCodeToString())) {
            return new Result(HttpStatus.FORBIDDEN, "无权访问");
        }
        if (expenseDto == null) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数[expenseDto为空]");
        }
        if (expenseDto.getId() == null || expenseDto.getId().isEmpty()) {
            return new Result(HttpStatus.BAD_REQUEST, "缺少参数[expenseDto.id为空]");
        }
        // 查询是否有该报销单
        Expense expense = expenseMapper.selectById(expenseDto.getId());
        if (expense == null) {
            return new Result(HttpStatus.BAD_REQUEST, "该报销单不存在");
        }
        expense.setStatus(expenseDto.getStatus());
        // 更新数据
        LambdaUpdateWrapper<Expense> expenseLUW = new LambdaUpdateWrapper<>();
        expenseLUW.eq(Expense::getId, expense.getId())
                .set(Expense::getStatus, expense.getStatus());
        expenseMapper.update(null, expenseLUW);

        if (expense.getStatus() == 1) {
            // 创建支出账单
            PaymentBilling paymentBilling = new PaymentBilling();
            paymentBilling.setOrderId(expense.getId());
            paymentBilling.setAmountPayable(expense.getPrice());
            paymentBilling.setDatePayable(LocalDate.now());
            paymentBilling.setBillsStatus(0);
            paymentBillingMapper.insert(paymentBilling);
            // 创建消息通知
            // 查询财务员角色
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState, BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_6.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()) {
                List<MessageNotification> msgList = new ArrayList<>();
                for (User finance : userList) {
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                    // 标题
                    msg.setTitle("有新的报销单待报销");
                    // 内容
                    User user1 = userMapper.selectById(expense.getUserId());
                    String content = user1.getNickName() + "申请报销" + expense.getPrice() + "元，已通过申请，待报销";
                    msg.setContent(content);
                    // 发布人为审核人
                    msg.setPublisherId(user.getId());
                    // 接收人为财务员
                    msg.setReceiverId(finance.getId());
                    // 关联id
                    msg.setRelevanceId(expense.getId());
                    // 类型为报销管理
                    msg.setMsgType(8);
                    // 子菜单为1报销列表
                    msg.setSubmenu(1);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
        String status;
        if (expense.getStatus() == 1) {
            // 已通过
            status = "已通过";
        } else {
            // 未通过
            status = "未通过";
        }
        MessageNotification msg = new MessageNotification();
        // 标题
        String title = "报销申请" + status;
        msg.setTitle(title);
        // 内容
        String content = "您的" + expense.getPrice() + "元报销申请" + status;
        msg.setContent(content);
        // 发布人为审核人
        msg.setPublisherId(user.getId());
        // 接收人为申请人
        msg.setReceiverId(expense.getUserId());
        // 关联id
        msg.setRelevanceId(expense.getId());
        // 类型为报销管理
        msg.setMsgType(8);
        // 子菜单为1报销列表
        msg.setSubmenu(1);
        // 状态为待处理
        msg.setStatus(0);
        msgNotificationMapper.insert(msg);
        return Result.success("操作成功");
    }
}
